#pragma once 

#include<iostream>
#include<semaphore.h> 
#include<vector>


namespace nm_ringqueue
{
    const int g_cap_default = 10;
    template<class T>
    class ringqueue
    {
      private:
        std::vector<T> _rq;
        int _cap;
        sem_t _blank_sem; //空位置
        sem_t _data_sem; //数据个数
        int c_step;
        int p_step;

      public:  
        ringqueue(int cap = g_cap_default):_cap(cap),_rq(cap)
        {
            //初始化空位置
            sem_init(&_blank_sem,0,cap) ; // 0 - cap 都是空位置
            sem_init(&_data_sem,0,0); //0 - 0 是有位置的数据，也就是一开始是没有数据的
            c_step = p_step = 0 ;//生产者和消费者都在0的位置
        }

        ~ringqueue()
        {
            sem_destroy(&_blank_sem);
            sem_destroy(&_data_sem);
        }

     public:
        void push(const T& in)
        {
            //生产者生产数据

            sem_wait(&_blank_sem); //生产者关心是否有空位，没有空位贼挂起,P操作 空位--
            
            //有空位置了，产生数据
            _rq[p_step] = in;

            sem_post(&_data_sem);//有新数据产生，v操作，数据++
            p_step++;
            p_step %= _cap;

        }
        void pop(T* out)
        {
            //消费者拿数据
            sem_wait(&_data_sem) ; //消费者只关心是否有数据，p操作，空位--
            *out = _rq[c_step];
            sem_post(&_blank_sem); //v操作 数据--
            
            c_step++;
            c_step %=_cap;
        }

    };
}
